package org.go.util;

import java.lang.annotation.Annotation;

import org.go.expcetion.SchedulerConfigException;

/**
 * 
 * @author hejie
 *
 */
public class ClassUtils {
	public static ClassLoader findClassloader() {
		// work-around set context loader for windows-service started jvms (QUARTZ-748)
		if (Thread.currentThread().getContextClassLoader() == null && ClassUtils.class.getClass().getClassLoader() != null) {
			Thread.currentThread().setContextClassLoader(ClassUtils.class.getClass().getClassLoader());
		}
		return Thread.currentThread().getContextClassLoader();
	}

	public static Class<?> loadClass(String className) throws ClassNotFoundException, SchedulerConfigException {
		try {
			ClassLoader cl = findClassloader();
			if (cl != null)
				return cl.loadClass(className);
			throw new SchedulerConfigException("Unable to find a class loader on the current thread or class.");
		} catch (ClassNotFoundException e) {
			if (ClassUtils.class.getClassLoader() != null)
				return ClassUtils.class.getClassLoader().loadClass(className);
			throw e;
		}
	}

	private static boolean isAnnotationPresentOnInterfaces(Class<?> clazz, Class<? extends Annotation> a) {
		if (clazz == null)
			return false;

		for (Class<?> i : clazz.getInterfaces()) {
			if (i.isAnnotationPresent(a))
				return true;
			if (isAnnotationPresentOnInterfaces(i, a))
				return true;
		}

		return false;
	}

	private static boolean isAnnotationPresentOnSuperClasses(Class<?> clazz, Class<? extends Annotation> a) {

		if (clazz == null)
			return false;

		Class<?> c = clazz.getSuperclass();
		while (c != null && !c.equals(Object.class)) {
			if (c.isAnnotationPresent(a))
				return true;
			if (isAnnotationPresentOnInterfaces(c, a))
				return true;
			c = c.getSuperclass();
		}

		if (isAnnotationPresentOnInterfaces(clazz.getSuperclass(), a))
			return true;

		return false;
	}

	public static boolean isAnnotationPresent(Class<?> clazz, Class<? extends Annotation> a) {
		if (clazz == null)
			return false;

		if (clazz.isAnnotationPresent(a))
			return true;

		if (isAnnotationPresentOnSuperClasses(clazz, a))
			return true;

		if (isAnnotationPresentOnInterfaces(clazz, a))
			return true;

		return false;
	}
}
